package gui;

import gui.event.GameController;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class MapViewPort extends JLayeredPane {
	private int speed = 10;
	private JComponent view;
	private int x, y;
	private boolean xResizable = true;
	private boolean yResizable = true;
	private ToolContainer tools;
	private Component glass;
	
	public MapViewPort(){
		initViewPort();
	}
	
	public MapViewPort(JComponent view){
		initViewPort();
		this.view = view;
		add(this.view);
		validate();
	}
	
	public void setView(JComponent view){
		if(this.view != null){
			remove(this.view);
		}
		this.view = view;
		add(this.view);
		validate();
		initResizability();
	}
	
	public void setToolContainer(ToolContainer tools){
		this.tools = tools;
		this.tools.setLocation(0, getHeight() - tools.getImage().getHeight());
		glass = MainWindow.mainWindow.getGlassPane();
		MainWindow.mainWindow.setGlassPane(tools);
		tools.setVisible(false);
		tools.setDimension(this.getSize());
	}
	
	private void initViewPort() {
		setLayout(null);
		setFocusable(true);
		addKeyListener(new ArrowListener(this));
		xResizable = true;
		yResizable = true;
		glass = MainWindow.mainWindow.getGlassPane();
	}
	
	public void centerView(){		
		x = (getWidth() - view.getWidth()) >> 1;
		y = (getHeight() - view.getHeight()) >> 1;
	}
	
	public void initResizability(){
		centerView();
		
		if(view.getWidth() < getWidth()){
			xResizable = false;
		} else {
			x = view.getLocation().x;
			
			if( x < getWidth() - view.getWidth() ){
				x = getWidth() - view.getWidth();
			} else if(x > 0) {
				x = 0;
			}
		}
		
		if(view.getHeight() < getHeight()){
			yResizable = false;
		} else {
			y = view.getLocation().y;
			
			if( y < getHeight() - view.getHeight() ){
				y = getHeight() - view.getHeight();
			} else if(y > 0) {
					y = 0;
			}
		}
		
		view.setLocation(x, y);
	}
	
	public JComponent getView(){
		return view;
	}
	
	public void quit(){
		if(tools != null){
			MainWindow.mainWindow.setGlassPane(glass);
			tools.setVisible(false);
		}
	}
	
	public void reset(){
		if(tools != null) {
			glass = MainWindow.mainWindow.getGlassPane();
			MainWindow.mainWindow.setGlassPane(tools);
		}
	}
	
	// sets the horizontal and vertical scrolling speed
	public void setSpeed(int speed){
		this.speed = speed;
	}
	
	// returns the scrolling speed
	public int getSpeed(){
		return speed;
	}
	
	// listener for the arrow keys
	private class ArrowListener extends KeyAdapter{
		private int vx, vy; // actual speed of moving view
		private boolean upNotPressed = true, downNotPressed = true, leftNotPressed = true, rightNotPressed = true;
		private int countPressed = 0;
		private Timer timer;
		private MapViewPort mvp;
		
		public ArrowListener(MapViewPort mvp){
			this.mvp = mvp;
			timer = new Timer(25, new ActionListener(){
				private int temp;
				
				public void actionPerformed(ActionEvent arg0) {
					x += vx;		// calculating next position of view on x axis
					y += vy;		// calculating next position of view on y axis
					
					if(xResizable){
						temp = getWidth() - view.getWidth();
						
						if( x < temp ){ 						// If it is lefter than should
							x = temp;
						} else if(x > 0) {							// If it is righter than should
							x = 0;
						}
					}
					
					if(yResizable){
						temp = getHeight() - view.getHeight();
							
						if( y < temp ){								// If it is upper than should
							y = temp;
						} else if(y > 0) {							// If it is downer than should
							y = 0;
						}
					}
					
					view.setLocation(x, y);
				}
			});
			
			timer.setRepeats(true);
		}
		
		public void keyPressed(KeyEvent k){
			int code = k.getKeyCode();

			switch(code){
			case KeyEvent.VK_RIGHT 	:
				if(rightNotPressed && xResizable){
					rightNotPressed = false;
					vx -= speed;
					if(countPressed==0)		//No keys were pressed until this key. The timer must start (again)
						timer.start();
					countPressed++;
				}
				break;
			case KeyEvent.VK_LEFT 	:
				if(leftNotPressed && xResizable){
					leftNotPressed = false;
					vx += speed;
					if(countPressed==0)
						timer.start();
					countPressed++;
				}
				break;
			case KeyEvent.VK_UP	:
				if(upNotPressed && yResizable){
					upNotPressed = false;
					vy += speed;
					if(countPressed==0)
						timer.start();
					countPressed++;
				}
				break;
			case KeyEvent.VK_DOWN	:
				if(downNotPressed && yResizable){
					downNotPressed = false;
					vy -= speed;
					if(countPressed==0)
						timer.start();
					countPressed++;
				}
				break;
			case KeyEvent.VK_SPACE	:
				if(tools != null){
					tools.setVisible( ! tools.isVisible() );
				}
				break;
			case KeyEvent.VK_ESCAPE	:
				quit();
				MainWindow.mainWindow.switchToMainMenu();
				GameController.stop();
				break;
			case KeyEvent.VK_F1 :
				quit();
				if(mvp.getParent() instanceof MapEditor){
					MainWindow.mainWindow.switchToHelp(HelpMenu.EDITOR);
				} else {
					MainWindow.mainWindow.switchToHelp(HelpMenu.GAME);
				}
				break;
			}
		}
		
		// If a key has been released it will be activated.
		public void keyReleased(KeyEvent k){
			int code = k.getKeyCode();
			switch(code){
				case KeyEvent.VK_RIGHT:
					if(xResizable){
						vx += speed;
						rightNotPressed = true;
						countPressed--;
					}
					break;
				case KeyEvent.VK_LEFT:
					if(xResizable){
						vx -= speed;
						leftNotPressed = true;
						countPressed--;
					}
					break;
				case KeyEvent.VK_UP:
					if(yResizable){
						vy -= speed;
						upNotPressed = true;
						countPressed--;
					}
					break;
				case KeyEvent.VK_DOWN:
					if(yResizable){
						vy += speed;
						downNotPressed = true;
						countPressed--;
					}
					break;
			}
			
			// No more key. The timer became useless temporary.
			if(countPressed == 0)
				timer.stop();
		}
	}
}